﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WinScriptEngine.Parses.Impl;
using WinScriptEngine.Parses.Interface;
using WinScriptEngine.Parses.Scope;

namespace WinScriptEngine.Parses.Basic
{
    class OperatorMethod
    {
        /// <summary>
        /// 从执行环境中获取某符号
        /// </summary>
        /// <param name="invoke">执行环境</param>
        /// <param name="symbol">符号数值</param>
        /// <returns>符号对应的数值</returns>
        public static dynamic GetValue(InvokeEnvironment invoke, Metadata symbol = null)
        {
            if (symbol == null)
                symbol = invoke.results.Pop();
            
            if (symbol.type != MetadataType.Symbol)
                return symbol.@object;

            return invoke.symbols.Get(symbol.@object).@object;
        }
        /// <summary>
        /// 在当前执行环境中添加符号
        /// </summary>
        /// <param name="invoke">当前执行环境</param>
        /// <param name="symbol">添加的符号</param>
        /// <param name="value">符号对应的的数值</param>
        /// <returns>符号对应的的数值</returns>
        public static dynamic SetValue(InvokeEnvironment invoke, Metadata symbol = null, dynamic value = null)
        {
            if (value == null)
            {
                value = invoke.results.Pop();
                value = GetValue(invoke, value);
            }

            if (symbol == null)
                symbol = invoke.results.Pop();

            if (symbol.type != MetadataType.Symbol)
                throw new OperatorRuntimeException("表达式必须是可修改的左值");

            invoke.symbols.Set(symbol.@object, new Metadata(MetadataType.Value, value));
            return value;
        }
        /// <summary>
        /// 未实现的运算符，委托源自<see cref="OperatorCallback"/>
        /// </summary>
        /// <param name="vCpu"></param>
        /// <returns></returns>
        public static bool NotImplemented(InvokeEnvironment vCpu)
        {
            throw new NotImplementedException();
        }
        public static bool Mul(InvokeEnvironment vCpu)
        {
            dynamic num2 = GetValue(vCpu);
            dynamic num1 = GetValue(vCpu);
            Console.WriteLine($"{num1} * {num2}");
            vCpu.results.Push(new Metadata(MetadataType.Value, num1 * num2));
            return true;
        }
        public static bool Div(InvokeEnvironment vCpu)
        {
            dynamic num2 = GetValue(vCpu);
            dynamic num1 = GetValue(vCpu);
            Console.WriteLine($"{num1} / {num2}");
            vCpu.results.Push(new Metadata(MetadataType.Value, num1 / num2));
            return true;
        }
        public static bool Add(InvokeEnvironment vCpu)
        {
            dynamic num2 = GetValue(vCpu);
            dynamic num1 = GetValue(vCpu);
            Console.WriteLine($"{num1} + {num2}");
            vCpu.results.Push(new Metadata(MetadataType.Value, num1 + num2));
            return true;
        }
        public static bool Sub(InvokeEnvironment vCpu)
        {
            dynamic num2 = GetValue(vCpu);
            dynamic num1 = GetValue(vCpu);
            Console.WriteLine($"{num1} - {num2}");
            vCpu.results.Push(new Metadata(MetadataType.Value, num1 - num2));
            return true;
        }
        public static bool Plus(InvokeEnvironment vCpu)
        {
            dynamic num1 = GetValue(vCpu);
            vCpu.results.Push(new Metadata(MetadataType.Value, num1));
            Console.WriteLine($"+{num1}");
            return true;
        }
        public static bool Neg(InvokeEnvironment vCpu)
        {
            dynamic num1 = GetValue(vCpu);
            vCpu.results.Push(new Metadata(MetadataType.Value, -num1));
            Console.WriteLine($"-{num1}");
            return true;
        }
        public static bool Xor(InvokeEnvironment vCpu)
        {
            dynamic num2 = GetValue(vCpu);
            dynamic num1 = GetValue(vCpu);
            Console.WriteLine($"{num1} ^ {num2}");
            vCpu.results.Push(new Metadata(MetadataType.Value, num1 ^ num2));
            return true;
        }
        public static bool Reverse(InvokeEnvironment vCpu)
        {
            dynamic num1 = GetValue(vCpu);
            vCpu.results.Push(new Metadata(MetadataType.Value, ~num1));
            Console.WriteLine($"~{num1}");
            return true;
        }
        public static bool Surplus(InvokeEnvironment vCpu)
        {
            dynamic num2 = GetValue(vCpu);
            dynamic num1 = GetValue(vCpu);
            Console.WriteLine($"{num1} % {num2}");
            vCpu.results.Push(new Metadata(MetadataType.Value, num1 % num2));
            return true;
        }
        public static bool Assign(InvokeEnvironment vCpu)
        {
            Metadata value = new Metadata(MetadataType.Value, SetValue(vCpu));
            vCpu.results.Push(value);
            return true;
        }
    }
}
